export class SnowFlake{
    renderer;
    FOCUS_POSITION = 300;
    FAR_LIMIT = 600;
    MAX_RIPPLE_COUNT = 100;
    RIPPLE_RADIUS = 100;
    SURFACE_RATE = 1.5;
    SINK_OFFSET = 20;
    x: number = 0;
    y: number = 0;
    z: number = 0;
    vx: number = 0;
    vy: number = 0;
    theta: number = 0;
    phi: number = 0;
    psi: number = 0;
    dpsi: number = 0;
    opacity: number = 0;
    endTheta: boolean = false;
    endPhi: boolean = false;
    rippleCount: number = 0;
    offsetY: number = 0;
    thresholdY: number = 0;
    entityColor: any;
    shadowColor: any;
    constructor(renderer: any, isRandom: boolean) {
        this.renderer = renderer;
	    this.init(isRandom);
    }
    init(isRandom: boolean) {
        this.x = this.getRandomValue(-this.renderer.width, this.renderer.width);
		this.y = isRandom ? this.getRandomValue(0, this.renderer.height) : this.renderer.height * 1.5;
		this.z = this.getRandomValue(0, this.FAR_LIMIT);
		this.vx = this.getRandomValue(-2, 2);
		this.vy = -2;
		this.theta = this.getRandomValue(0, Math.PI * 2);
		this.phi = this.getRandomValue(0, Math.PI * 2);
		this.psi = 0;
		this.dpsi = this.getRandomValue(Math.PI / 600, Math.PI / 300);
		this.opacity = 0;
		this.endTheta = false;
		this.endPhi = false;
		this.rippleCount = 0;
		
		var axis = this.getAxis(),
			theta = this.theta + Math.ceil(-(this.y + this.renderer.height * this.SURFACE_RATE) / this.vy) * Math.PI / 500;
		theta %= Math.PI * 2;
		
		this.offsetY = 40 * ((theta <= Math.PI / 2 || theta >= Math.PI * 3 / 2) ? -1 : 1);
        this.thresholdY = this.renderer.height / 2 + this.renderer.height * this.SURFACE_RATE * axis.rate;
        /**
         * context.createRadialGradient(x0,y0,r0,x1,y1,r1);
         * x0	渐变的开始圆的 x 坐标
         * y0	渐变的开始圆的 y 坐标
         * r0	开始圆的半径
         * x1	渐变的结束圆的 x 坐标
         * y1	渐变的结束圆的 y 坐标
         * r1	结束圆的半径
         */
        // 颜色
		this.entityColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
		// this.entityColor.addColorStop(0, 'hsl(0, 0%, ' + 50 * (0.3 + axis.rate) + '%)');
		// this.entityColor.addColorStop(0.05, 'hsl(0, 2%,' + 55 * (0.3 + axis.rate) + '%)');
		// this.entityColor.addColorStop(1, 'hsl(0, 4%, ' + 60 * (0.3 + axis.rate) + '%)');
		this.entityColor.addColorStop(0, 'hsl(330, 70%, ' + 50 * (0.3 + axis.rate) + '%)');
		this.entityColor.addColorStop(0.05, 'hsl(330, 40%,' + 55 * (0.3 + axis.rate) + '%)');
		this.entityColor.addColorStop(1, 'hsl(330, 20%, ' + 70 * (0.3 + axis.rate) + '%)');
    }
    getRandomValue(min: number, max: number){
		return min + (max - min) * Math.random();
	}
	getAxis(){
		var rate = this.FOCUS_POSITION / (this.z + this.FOCUS_POSITION),
			x = this.renderer.width / 2 + this.x * rate,
			y = this.renderer.height / 2 - this.y * rate;
		return {rate : rate, x : x, y : y};
	}
	renderCherry(context: any, axis: any){
		context.beginPath();
        context.moveTo(0, 10);
        // 花瓣
        //bezierCurveTo 绘制一条三次贝塞尔曲线
        /**
         *  开始点：moveTo(20,20)
            控制点 1：bezierCurveTo(20,100,200,100,200,20)
            控制点 2：bezierCurveTo(20,100,200,100,200,20)
            结束点：bezierCurveTo(20,100,200,100,200,20)

         * context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
         * cp1x	第一个贝塞尔控制点的 x 坐标
         * cp1y	第一个贝塞尔控制点的 y 坐标
         * cp2x	第二个贝塞尔控制点的 x 坐标
         * cp2y	第二个贝塞尔控制点的 y 坐标
         * x	结束点的 x 坐标
         * y	结束点的 y 坐标
         */
        context.bezierCurveTo(-15, 5, -5, -15, 0, -10);
		context.bezierCurveTo(5, -15, 15, 5, 0, 10);
        // 上边一半
        // context.bezierCurveTo(-30, 10, -10, -20, 0, -20);
        // 下边一半
		// context.bezierCurveTo(10, 30, 30, 10, 0, 20);
		context.fill();
		// for(var i = -2; i < 2; i++){
		// 	context.beginPath();
        //     context.moveTo(0, 20);
        //     // 纹路
		// 	// context.quadraticCurveTo(i * 6, 5, i * 2, -12 + Math.abs(i) * 2);
		// 	context.stroke();
		// }
	}
	render(context: any){
		var axis = this.getAxis();
		if(axis.y == this.thresholdY && this.rippleCount < this.MAX_RIPPLE_COUNT){
			// context.save();
			// context.lineWidth = 2;
			// context.strokeStyle = 'hsla(0, 0%, 100%, ' + (this.MAX_RIPPLE_COUNT - this.rippleCount) / this.MAX_RIPPLE_COUNT + ')';
			// context.translate(axis.x + this.offsetY * axis.rate * (this.theta <= Math.PI ? -1 : 1), axis.y);
			// context.scale(1, 0.3);
			// context.beginPath();
			// context.arc(0, 0, this.rippleCount / this.MAX_RIPPLE_COUNT * this.RIPPLE_RADIUS * axis.rate, 0, Math.PI * 2, false);
			// context.stroke();
			// context.restore();
			// this.rippleCount++;
		}
		if(axis.y < this.thresholdY || (!this.endTheta || !this.endPhi)){
			if(this.y <= 0){
				this.opacity = Math.min(this.opacity + 0.01, 1);
			}
			// context.save();
			// context.globalAlpha = this.opacity;
			// context.fillStyle = this.shadowColor;
			// context.strokeStyle = 'hsl(330, 30%,' + 40 * (0.3 + axis.rate) + '%)';
			// context.translate(axis.x, Math.max(axis.y, this.thresholdY + this.thresholdY - axis.y));
			// context.rotate(Math.PI - this.theta);
			// context.scale(axis.rate * -Math.sin(this.phi), axis.rate);
			// context.translate(0, this.offsetY);
			// this.renderCherry(context, axis);
			// context.restore();
		}
		context.save();
		context.fillStyle = this.entityColor;
        // context.fillStyle = "rgba(0,0,0,.2)";
        // context.globalAlpha = Math.min(this.opacity + 0.01, 1);
		context.strokeStyle = 'hsl(330, 40%,' + 70 * (0.3 + axis.rate) + '%)';
		context.translate(axis.x, axis.y + Math.abs(this.SINK_OFFSET * Math.sin(this.psi) * axis.rate));
		context.rotate(this.theta);
		context.scale(axis.rate * Math.sin(this.phi), axis.rate);
		context.translate(0, this.offsetY);
		this.renderCherry(context, axis);
        context.restore();
        // return;
		
		if(this.y <= -this.renderer.height / 4){
			if(!this.endTheta){
				for(var theta = Math.PI / 2, end = Math.PI * 3 / 2; theta <= end; theta += Math.PI){
					if(this.theta < theta && this.theta + Math.PI / 200 > theta){
						this.theta = theta;
						this.endTheta = true;
						break;
					}
				}
			}
			if(!this.endPhi){
				for(var phi = Math.PI / 8, end = Math.PI * 7 / 8; phi <= end; phi += Math.PI * 3 / 4){
					if(this.phi < phi && this.phi + Math.PI / 200 > phi){
						this.phi = Math.PI / 8;
						this.endPhi = true;
						break;
					}
				}
			}
		}
		if(!this.endTheta){
			if(axis.y == this.thresholdY){
				this.theta += Math.PI / 200 * ((this.theta < Math.PI / 2 || (this.theta >= Math.PI && this.theta < Math.PI * 3 / 2)) ? 1 : -1);
			}else{
				this.theta += Math.PI / 500;
			}
			this.theta %= Math.PI * 2;
		}
		if(this.endPhi){
			if(this.rippleCount == this.MAX_RIPPLE_COUNT){
				this.psi += this.dpsi;
				this.psi %= Math.PI * 2;
			}
		}else{
			this.phi += Math.PI / ((axis.y == this.thresholdY) ? 200 : 500);
			this.phi %= Math.PI;
		}
        if (this.y <= -this.renderer.height * this.SURFACE_RATE) {
            // 底部波纹飘落动效
			// this.x += 2;
			this.y = -this.renderer.height * this.SURFACE_RATE;
		}else{
			this.x += this.vx;
			this.y += this.vy;
		}
		return this.z > -this.FOCUS_POSITION && this.z < this.FAR_LIMIT && this.x < this.renderer.width * 1.5;
	}

}